module Image2Borders where

import Data.Vector.Storable 
                    as SV(Vector, 
                          generate, 
                          unsafeWith, 
                          unsafeFromForeignPtr0, 
                          length)
import Codec.Picture
import Codec.Picture.Types
import GHC.Word(Word8)
import Data.ByteString as BS(ByteString, readFile, writeFile)
import Prelude hiding (readFile, writeFile, length)
import Foreign
import Foreign.C.Types
import Foreign.Ptr

{-# LANGUAGE C, ForeignFunctionInterface #-}

#include "gauss.h"

foreign import ccall safe "gauss.h transform"
    c_transform :: Ptr Word8 -> CInt -> CInt -> Ptr Word8 -> IO ()

createImage :: ByteString -> Either String (Image PixelRGB8)
createImage input = 
       case decodeImage input of
            Left err -> Left err
            Right im -> 
              Right $ 
              ( case im of 
                     ImageY8 y8Im         -> promoteImage y8Im :: Image PixelRGB8
                     ImageYCbCr8 ycbcr8Im -> convertImage ycbcr8Im :: Image PixelRGB8
                     ImageYA8 ya8Im       -> promoteImage ya8Im :: Image PixelRGB8
                     ImageRGB8 rgb8Im     -> rgb8Im
                     ImageRGBA8 rgba8Im   -> dropAlphaLayer rgba8Im
              ) 

transform :: FilePath -> IO ()
transform name = do
    content <- BS.readFile name
    case (createImage content) of
         Left err -> putStrLn err
         Right im -> do
            let w = fromIntegral $ imageWidth im
                h = fromIntegral $ imageHeight im
                oldData = imageData im
                len = length oldData
            pResult <- mallocForeignPtrArray len
            withForeignPtr 
                pResult 
                (\pRes -> unsafeWith oldData
                            (\pDat -> c_transform pDat w h pRes ) ) 
            let newData = unsafeFromForeignPtr0 pResult len
                newContent = encodePng $ ( im{ imageData = newData } :: Image PixelRGB8)
            BS.writeFile "output.png" newContent
